(ns utilities.GUI
	(:gen-class)
	(:use utilities.DBMain)
	(:use utilities.cliente)
	(:use utilities.prompt))
(import '(javax.swing JFrame JLabel JTable JButton JScrollPane JPanel JCheckBox
		JFormattedTextField JTextField JSpinner SpinnerNumberModel SpinnerListModel)
	'(javax.swing.table TableModel)
	'(java.text NumberFormat)
	'(java.awt.event ActionListener)
	'(java.awt BorderLayout Dimension FlowLayout GridLayout))

(defn fill-table 
	"Fills the table with the records sent."
	[records]  
	(let [data records
		row (first data)	
		colcnt (count row)	
		rowcnt (count data)
		]    
		(proxy [TableModel] []      
			(addTableModelListener [tableModelListener])      
			(getColumnClass [columnIndex] Object)      
			(getColumnCount [] colcnt)      
			(getColumnName [columnIndex]		  
				(name (nth (keys row) columnIndex)))	  	      
			(getRowCount [] rowcnt)      
			(getValueAt [rowIndex columnIndex]	
				(nth (vals (nth data rowIndex)) columnIndex))	
			(isCellEditable [rowIndex columnIndex] false)
			(removeTableModelListener [tableModelListener]))))
;---------------------------------------------------------------------------------------------------------------------			
(defn createoptions
	"Displays the options to create a new record."
	[instructionlabel action datebox fields smokingfield]
	(.setText action "Create")
	(.setText instructionlabel "Fill the data that the new record will have.")
	(.setValue smokingfield "")
	(.setVisible datebox false)
	(.setSelected datebox true)
	(loop [fields fields
		_ nil]
		(if (first fields)
			(recur (rest fields) (.setText (first fields) "")))))
;---------------------------------------------------------------------------------------------------------------------
(defn findoptions
	"Displays the options to find a record."
	[instructionlabel action datebox fields smokingfield]
	(.setText action "Find")
	(.setText instructionlabel "Fill the data of the record(s) you want to find.")
	(.setValue smokingfield "")
	(.setVisible datebox true)
	(.setSelected datebox false)
	(loop [fields fields
		_ nil]
		(if (first fields)
			(recur (rest fields) (.setText (first fields) "")))))
;---------------------------------------------------------------------------------------------------------------------
(defn fillfields 
	"Fill the fields of the GUI"
	[upnum numrec namefield locationfield sizefield smokingfield ratefield yearspinner monthspinner dayspinner ownerfield]
	(let [record (reading numrec)]
		(.setText namefield (:name record))
		(.setText locationfield (:location record))
		(.setText sizefield (:size record))
		(.setValue smokingfield (:smoking record))
		(.setValue ratefield (. Double parseDouble (.substring (:rate record) 1)))
		(.setValue yearspinner (. Integer parseInt (.substring (:date record) 0 4)))
		(.setValue monthspinner (. Integer parseInt (.substring (:date record) 5 7)))
		(.setValue dayspinner (. Integer parseInt (.substring (:date record) 8)))
		(.setText ownerfield (:owner record))
		(.setText upnum (str numrec))))
;---------------------------------------------------------------------------------------------------------------------
(defn updateoptions
	"Displays the options to update a record."
	[upnum table instructionlabel action datebox namefield locationfield sizefield smokingfield ratefield yearspinner monthspinner
	dayspinner ownerfield]
	(.setText action "Update")
	(.setText instructionlabel "Change the data to be updated.")
	(.setVisible datebox false)
	(.setSelected datebox true)
	(loop
		[i 0
		size (.getSize table)]
		(if (< i (.getRowCount table))
			(if(.isCellSelected table i 0)
				(fillfields upnum i namefield locationfield sizefield smokingfield ratefield yearspinner monthspinner
					dayspinner ownerfield)
				(recur (inc i) size)))))
;---------------------------------------------------------------------------------------------------------------------
(defn delete-Action 
	"Erase the chosen record."
	[table]
	(loop
		[i 0
		size (.getSize table)]
		(if (< i (.getRowCount table))
			(if(.isCellSelected table i 0)
				(delete i)
				(recur (inc i) size)))))
;---------------------------------------------------------------------------------------------------------------------
(defn updatedb-Action 
	"updates the database from the server."
	[ip]
	(peticiona ip)
)
;---------------------------------------------------------------------------------------------------------------------
(defn add-$
	"Adds the symbol $ to the rate."
	[rate]
	(if (> (.length rate) 0)
		(if (.equals "$" (.substring rate 0 1))
			rate
			(str "$" rate))
		rate))
;---------------------------------------------------------------------------------------------------------------------
(defn addzero
	"Adds a zero if the number length is less than 2."
	[number]
	(if (< (.length (str number)) 2)
		(str 0 number)
		number))
;---------------------------------------------------------------------------------------------------------------------
(defn joindate
	"Joins the year, month and day."
	[datebox year month day]
	(let [newmonth (addzero month)
		newday (addzero day)]
		(if (.isSelected datebox)
			(str year "/" newmonth "/" newday)
			"")))
;---------------------------------------------------------------------------------------------------------------------
(defn doaction
	"Choose what todo acording to the text of the button."
	[upnum actiontext table ownerfield datebox yearspinner monthspinner dayspinner ratefield smokingfield sizefield locationfield 
	namefield]
	(if (.equals actiontext "Find")
		(.setModel table (fill-table (getrecordlist (find-registers {:owner (.getText ownerfield),
		:date (joindate datebox (.getValue yearspinner) (.getValue monthspinner) (.getValue dayspinner)), 
		:rate (add-$ (.getText ratefield)), :smoking (.getValue smokingfield), :size (.getText sizefield), 
		:location (.getText locationfield), :name (.getText namefield)})))))
	(if (.equals actiontext "Create")
		(create {:owner (.getText ownerfield), 
		:date (joindate datebox (.getValue yearspinner) (.getValue monthspinner) (.getValue dayspinner)), 
		:rate (add-$ (.getText ratefield)), :smoking (.getValue smokingfield), :size (.getText sizefield), 
		:location (.getText locationfield), :name (.getText namefield)}))
	(if (.equals actiontext "Update")
		(update (. Integer parseInt (.getText upnum)) {:owner (.getText ownerfield), 
		:date (joindate datebox (.getValue yearspinner) (.getValue monthspinner) (.getValue dayspinner)), 
		:rate (add-$ (.getText ratefield)), :smoking (.getValue smokingfield), :size (.getText sizefield), 
		:location (.getText locationfield), :name (.getText namefield)})))
;---------------------------------------------------------------------------------------------------------------------
(defn client
	"Displays a GUI window."
	[ip]
	(let [_ (peticiona ip)
		frame (JFrame. "Data Base Manager")
		create (JButton. "Create")
		update (JButton. "Update")
		delete (JButton. "Delete")
		finder (JButton. "Find")
		action (JButton. "Find")
		updatedb (JButton. "Refresh Database")
		upnum (JLabel. "0")
		instructionlabel (JLabel. "Fill the data of the record(s) you want to find." JLabel/CENTER)
		namelabel (JLabel. "Name:" JLabel/RIGHT)
		blanklabel1 (JLabel. "<<< Click to Commit.")
		blanklabel2 (JLabel. "")
		locationlabel (JLabel. "Location:" JLabel/RIGHT)
		sizelabel (JLabel. "Size:" JLabel/RIGHT)
		smokinglabel (JLabel. "Smoking:" JLabel/RIGHT)
		ratelabel (JLabel. "Rate: $" JLabel/RIGHT)
		datelabel (JLabel. "Date:" JLabel/RIGHT)
		ownerlabel (JLabel. "Owner:" JLabel/RIGHT)
		rateformat (. NumberFormat getInstance)
		namefield (JTextField.)
		locationfield (JTextField.)
		sizefield (JTextField.)
		smokingfield (JSpinner. (SpinnerListModel. (list "" "Y" "N")))
		ratefield (JFormattedTextField. rateformat)
		yearspinner (JSpinner. (SpinnerNumberModel. 2010 2003 2020 1))
		monthspinner (JSpinner. (SpinnerNumberModel. 3 1 12 1))
		dayspinner (JSpinner. (SpinnerNumberModel. 23 1 31 1))
		datebox (JCheckBox.)
		ownerfield (JTextField.)
		table (JTable. (fill-table (getrecords)))
		scroll (JScrollPane. table)
		panelNorth (JPanel.)
		paneldate (JPanel.)
		panelSouth (JPanel.)
		gridLayout (GridLayout. 0 4 5 5)
		updatedbAction(proxy [ActionListener][]
			(actionPerformed [event]
				(updatedb-Action ip)
				(.setModel table (fill-table (getrecords)))))
		deleteAction(proxy [ActionListener] []
			(actionPerformed [event]
				(delete-Action table)
				(if (=(sendact ip) 1)
					(do 
						(sendnew ip)
					(updatedb-Action ip))
					(prompt)
				)
				(.setModel table (fill-table (getrecords)))))
		createAction (proxy [ActionListener] []
			(actionPerformed [event]
				(createoptions instructionlabel action datebox (list namefield locationfield sizefield ratefield ownerfield) smokingfield)
				(updatedb-Action ip)
				(.setModel table (fill-table (getrecords)))))
		updateAction (proxy [ActionListener] []
			(actionPerformed [event]
				(updateoptions upnum table instructionlabel action datebox namefield locationfield sizefield smokingfield ratefield yearspinner monthspinner
					dayspinner ownerfield)
				(updatedb-Action ip)
				(.setModel table (fill-table (getrecords)))))
		findAction (proxy [ActionListener] []
			(actionPerformed [event]				
				(findoptions instructionlabel action datebox (list namefield locationfield sizefield ratefield ownerfield) smokingfield)
				(updatedb-Action ip)
				(.setModel table (fill-table (getrecords)))))
		actionAction (proxy [ActionListener] []
			(actionPerformed [event]				
				(doaction upnum (.getText action) table ownerfield datebox yearspinner monthspinner dayspinner ratefield 
					smokingfield sizefield locationfield namefield)
					(if (not(.equals (.getText action) "Find"))
						(do
							(if (=(sendact ip) 1)
								(do
									(sendnew ip)
									(updatedb-Action ip))
								(prompt))
							(.setModel table (fill-table (getrecords)))))
					;(findoptions instructionlabel action datebox (list namefield locationfield sizefield ratefield ownerfield) smokingfield)
		))]
		(.setDefaultCloseOperation frame JFrame/EXIT_ON_CLOSE)
		(.setMinimumSize frame (Dimension. 800 600))
		(.setMinimumFractionDigits rateformat 2)
		(.setMaximumFractionDigits rateformat 2)
		(.setLayout panelNorth (FlowLayout.))
		(.setLayout paneldate (FlowLayout.))
		(.setLayout panelSouth gridLayout)
		(.add paneldate datebox)
		(.add paneldate yearspinner)
		(.add paneldate monthspinner)
		(.add paneldate dayspinner)
		(.add panelNorth create)
		(.add panelNorth update)
		(.add panelNorth delete)
		(.add panelNorth finder)
		(.add panelNorth updatedb)
		(.add panelSouth action)
		(.add panelSouth blanklabel1)
		(.add panelSouth instructionlabel)
		(.add panelSouth blanklabel2)
		(.add panelSouth namelabel)
		(.add panelSouth namefield)
		(.add panelSouth locationlabel)
		(.add panelSouth locationfield)
		(.add panelSouth sizelabel)
		(.add panelSouth sizefield)
		(.add panelSouth smokinglabel)
		(.add panelSouth smokingfield)
		(.add panelSouth ratelabel)
		(.add panelSouth ratefield)
		(.add panelSouth datelabel)
		(.add panelSouth paneldate)
		(.add panelSouth ownerlabel)
		(.add panelSouth ownerfield)
		(.addActionListener create createAction)
		(.addActionListener update updateAction)
		(.addActionListener finder findAction)
		(.addActionListener delete deleteAction)
		(.addActionListener action actionAction)
		(.addActionListener updatedb updatedbAction)
		(.add frame BorderLayout/NORTH panelNorth)
		(.add frame BorderLayout/CENTER scroll)
		(.add frame BorderLayout/SOUTH panelSouth)
		(.pack frame)
		(.setVisible frame true)))
;---------------------------------------------------------------------------------------------------------------------
